package com.hulk.Idempotent.util;



import com.hulk.Idempotent.annotation.Limitb;
import com.hulk.Idempotent.enums.LimitType;

import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;

import java.util.concurrent.TimeUnit;

/**
 * Created hulk  on 2019/05/28.
 * Content :redis限流
 */
@Slf4j
@NoArgsConstructor
public class RedisLimitStrategy extends LimitStrategy {

    private static  final LimitType REDIS = LimitType.REDIS;



    @Override
    public boolean execute (String key,  Limitb limit){

        if(REDIS!=limit.limitType()){

        }

        long count = incr(key, limit.seconds());
        if (count > limit.maxCount()) {
            log.warn(REDIS.name()+":限流中......");
            return false;
        }
        return true;
    }


    //TODO  此处应该用redis的漏桶实现，暂时简单实现。
    //自增方法
    private Long incr(String key, long liveTime) {
        RedisTemplate  limitbRedisTemplate = SpringContextHolder.getBean("limitbRedisTemplate",RedisTemplate.class);
        limitbRedisTemplate.setKeySerializer(new StringRedisSerializer());
        limitbRedisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, limitbRedisTemplate.getConnectionFactory());
        Long increment = entityIdCounter.getAndIncrement();
        //初始设置过期时间
        if ((null == increment || increment.longValue() == 0) && liveTime > 0) {
            //liveTime为秒数
            entityIdCounter.expire(liveTime, TimeUnit.SECONDS);
        }
        return increment;
    }


}
